package com.yyfax.pay.common.exception;

import org.apache.commons.lang3.StringUtils;

import com.yyfax.framework.common.OpResponse;
import com.yyfax.framework.exception.ApplicationException;
import com.yyfax.framework.exception.IErrors;

/**
 * API 前置的异常码划分为:
 *
 * @author maojian
 *         <li>支付模块错误码: 500000~500999</li> 501000开始
 * @date 2017-07-31 17:53:03
 * @since v1.0.0
 */
public enum PayExceptionCode implements IErrors<OpResponse> {
	SUCCESS(0, "成功"),
	/** 用于处理交易成功的数据，但是通知出现的金额异常等情况 */
	SUCCESS_EXCEPTION(1, "交易成功，数据异常"),

	ERROR_ILL_PARAMETER(100002, "参数不正确"),

	ERROR_SIGN_FAIL(100007, "签名失败"),

	ERR0R_DUPLICATE(100018, "操作频繁，请稍后再试"),

	// PAY_CODE_PAYOUT_FAIL
	ERROR_PAYOUT_FAIL(500101, "代付失败"),

	ERROR_PAID(500131, "订单已经支付"),

	ERROR_MERCHANT_NOT_EXISTS(500001, "商户不存在/无效"),

	ERROR_ILL_CONFIG_BANK_EXT(500010, "银行扩展配置异常"),

	// PAY_CODE_ORDER_DUPLICATE
	ERROR_ORDER_DUPLICATE(500116, "订单重复"),

	// PAY_CODE_UNKNOWN
	WARN_UNKNOWN(500124, "未知异常"),

	ERROR_MERCHANT_CONFIG_ILLEGAL(500134, "商户配置信息异常"),

	// PAY_CODE_REQ_TIME_OUT
	WARN_REQ_TIME_OUT(500210, "请求超时"),

	// PAY_CODE_DEALING
	DEALING(500211, "处理中/挂起"),

	// PAY_CODE_MERCHANT_NOT_SUPPORT_PAYMENT
	ERROR_NOT_SUPPORT_PAYMENT(500111, "不支持的支付通道"),

	ERROR_REFUND(500141, "退票"),

	/**************************************** 以下是新的异常代码 ，响应码从501000开始 ****************************************/

	ERROR_PAY_FAIL(501002, "支付失败"),

	TRADE_NOTIFY_RESULT_ERROR(501003, "通知交易失败"),

	USER_CHANGE_INFO_RESULT_ERROR(501004, "通知修改信息失败"),

	ORDER_NOT_FOUND(501005, "订单不存在"),

	/** 对应富友8210 */
	VERIFY_CODE_OVER_LIMIT(501006, "验证码发送次数超限"),
	/** 对应富友8143 */
	VERIFY_CODE_INVALID(501007, "验证码失效或错误"),

	WITHDRAW_CANCEL(501008, "提现退票"),

	QUERY_ERROR(501009, "查询失败"),

	/** 未开户 */
	ERROR_NOT_OPEN_ACCOUNT(501010, "未开户"),

	ERROR_BEFORE_SMS(501011, "操作失败，请先获取短信"),

	ACCOUNT_MUST_COMPAY_AND_PERSION(502000, "收付款登录账户必须一个是商户一个是个人用户"),

	/** 表示订单处理中的状态 */
	PROCESSING(502003, "处理中"),

	/**
	 * 待确认状态，订单状态未知，需要后期确认
	 */
	TO_CONFIRM(502004, "待确认"),

	/**************************************** 失败异常码 begin *************************************************************/

	ERROR_FILE_FAIL(503000, "操作文件异常"),

	PROTOCOL_DUPILICATE(503001, "重复签约"),

	UN_SIGN(503002, "未签约"),

	VERIFY_CODE_MAX_ERROR(503003, "验证超过输入超过最大次数"),
	
	/** 无效卡号*/
	INVALID_CARD_ID(503004, "无效卡号"),
	
	QUERY_OFTEN(503005, "查询频繁"),

	/** 该异常用于给业务方提示具体响应异常信息 */
	FAIL_TIP_MSG(500900, "存管操作异常"),

	ERROR_OPT_FAIL(500998, "操作失败"),

	/*** 系统错误 */
	SYS_ERROR(500999, "系统错误"),


	ERROR_PROTOCOL_SENDMSG(504001, "请求验证码失败"),

	ERROR_MSGCODE_FIRST(504002, "请先获取验证码"),

	ERROR_EXISI_PROTOCOL(504003, "已存在协议号"),

	ERROR_EXIST_RESULT(504004, "订单已出结果,重复请求"),

	ERROR_PROTOCOL_FAIL(504005, "协议支付请求失败"),

	ERROR_OP_EXCEPTION(504006, "协议操作异常"),

	ERROR_DATA_NOT_EQUAL(504007, "身份信息与已绑定身份信息不一致"),

	ERROR_DATA_EXCEPTION(504008, "数据异常"),

	ERROR_USER_PAYMENT_NOT_EXISTS(504009, "用户支付扩展信息不存在"),

	ERROR_PAYMENT_OR_PROTOCOLCODE_NOT_EXIST(504010, "未开通对应支付通道,或者协议号缺失"),

	ERROR_UNBIND_EXCEPTION(504011, "协议解绑异常"),

	ERROR_TOKEN_ERROR(504012, "请求协议绑定令牌错误"),

	ERROR_ORDER_STATE_NOT_INIT(504013, "订单状态不是初始化");
	/**************************************** 失败异常码 end *************************************************************/

	private int code;
	private String desc;

	private PayExceptionCode(int code, String desc) {
		this.code = code;
		this.desc = desc;
	}

	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public OpResponse parse() {
		OpResponse result = new OpResponse();
		result.setCode(code);
		result.setDisplay(desc);
		return result;
	}

	@Override
	public OpResponse parse(Object... args) {
		OpResponse result = new OpResponse();
		result.setCode(code);
		String formatReason = String.format(desc, args);
		result.setDisplay(formatReason);
		return result;
	}

	@Override
	public OpResponse parseMsg(String message, Object... args) {
		this.desc = message;
		return parse(args);
	}

	@Override
	public PayException exp() {
		return new PayException(code, desc);
	}

	@Override
	public PayException exp(Object... args) {
		String formatReason = String.format(desc, args);
		return new PayException(code, formatReason);
	}

	@Override
	public PayException expMsg(String message, Object... args) {
		String formatReason = "";
		if (StringUtils.isNotBlank(message)) {
			formatReason = String.format(message, args);
		}

		return new PayException(code, formatReason);
	}

	@Override
	public ApplicationException exp(Throwable arg0, Object... arg1) {
		return null;
	}

	@Override
	public ApplicationException expMsg(String arg0, Throwable arg1, Object... arg2) {
		return null;
	}

	public boolean isCode(int code) {
		return getCode() == code;
	}

	/**
	 * 判断响应码是否是处理中的状态
	 * 
	 * @author buyi
	 * @date 2018-05-12 03:14:49
	 * @since v2.1.5
	 * @param code
	 * @return
	 */
	public static boolean isToConfirm(int code) {
		if (WARN_UNKNOWN.isCode(code) || DEALING.isCode(code) || PROCESSING.isCode(code) || TO_CONFIRM.isCode(code)) {
			// 未知，处理中，都表示为需要确认的响应码
			return true;
		}

		return false;
	}

	/**
	 * 判断响应码是为超时
	 * 
	 * @author buyi
	 * @date 2018-05-12 03:29:27
	 * @since v2.1.5
	 * @param code
	 * @return
	 */
	public static boolean isTimeout(int code) {
		if (WARN_REQ_TIME_OUT.isCode(code)) {
			// 未知，处理中，超时，都表示为需要确认的响应码
			return true;
		}

		return false;
	}

}
